package java_thinking.unit_21._21_11;

import net.jcip.annotations.ThreadSafe;

/**
 * @Desc:   11-8 基于散列的 Map 中使用的锁分段技术
 * @author: cww
 * @DateTime: 2019-06-22 16:04
 */
@ThreadSafe
public class StripedMap {
    /**
     * 同步策略：buckets[n] 由 locks[n % N_LOCKS] 来保护
     */
    private static final int N_LOCKS = 16;
    private final Node[] buckets;
    private final Object[] locks;

    public StripedMap(int numBuckets) {
        this.buckets = new Node[numBuckets];
        this.locks = new Object[N_LOCKS];
        for (int i = 0; i < locks.length; i++) {
            locks[i] = new Object();
        }
    }

    private static class Node {
        Node next;
        Object key;
        Object value;
    }

    private final int hash(Object key) {
        return Math.abs(key.hashCode() % buckets.length);
    }

    public Object get(Object key) {
        int hashKey = hash(key);
        synchronized (locks[hashKey % N_LOCKS]) {
            for (Node m = buckets[hashKey]; m != null; m = m.next) {
                if (m.key.equals(key)) {
                    return m.value;
                }
            }
        }
        return null;
    }

    /**
     * clear 方法需要获得所有锁，但在这段代码中并不是原子操作，因为可能在清除某个锁时，其他锁被获得并插入数据
     * 如果要将该操作成为一个原子操作，那么需要同时获得所有的锁，另外像 size 与 isEmpty 方法类似，
     */
    public void clear() {
        for (int i = 0; i < buckets.length; i++) {
            synchronized (locks[i % N_LOCKS]) {
                buckets[i] = null;
            }
        }
    }

}
